package jusda.caa.minio.service;

import com.google.common.io.ByteStreams;
import jusda.caa.minio.config.CustomException;
import jusda.caa.minio.entity.FileAttributeDTO;
import jusda.caa.minio.entity.UploadResultDTO;
import jusda.caa.minio.utils.MinioUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FileService {

    @Value("${file.service.host}")
    private String host;
    private final String GET_FILE_URL = "/files/get";
    private final String GET_FILE_STREAM = "/files/getStream";

    @Autowired
    MinioUtils minioUtils;

    /**
     * 文件上传
     *
     * @param bucketName  文件桶名称
     * @param inputStream 文件流
     * @param fileName    源文件名称 不带后缀
     * @param description 源文件描述
     * @param fileSuffix  文件后缀名
     * @return
     * @throws CustomException
     */
    public UploadResultDTO uploadFile(String bucketName, InputStream inputStream, String fileName, String description, String fileSuffix) throws CustomException {
        UploadResultDTO uploadReturnDTO = new UploadResultDTO();
        fileSuffix = StringUtils.lowerCase(StringUtils.remove(fileSuffix, "."));
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                throw new CustomException(1000, "文件桶名称不存在");
            }
            StringBuilder fileNameBuilder = new StringBuilder();
            fileNameBuilder.append(fileName);
            fileNameBuilder.append(System.currentTimeMillis());
            String fileNameTemp = DigestUtils.md5DigestAsHex(fileNameBuilder.toString().getBytes());

            StringBuilder targetNameBuilder = new StringBuilder();
            targetNameBuilder.append(fileSuffix);
            targetNameBuilder.append("_");
            targetNameBuilder.append(fileNameTemp);
            targetNameBuilder.append(".");
            targetNameBuilder.append(fileSuffix);
            String newFileName = targetNameBuilder.toString();

            minioUtils.uploadFile(bucketName, newFileName, inputStream, fileName, description);
            uploadReturnDTO.setBucketName(bucketName);
            uploadReturnDTO.setFileName(fileName);
            uploadReturnDTO.setGetFileURL(host + GET_FILE_URL + "/" + bucketName + "/" + newFileName);
            uploadReturnDTO.setGetFileStream(host + GET_FILE_STREAM + "/" + bucketName + "/" + newFileName);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException(-1, e.getMessage());
        }
        return uploadReturnDTO;
    }

    /**
     * 获取文件访问路径
     *
     * @param bucketName 文件桶名称
     * @param targetName 文件名
     * @return
     * @throws CustomException
     */
    public String getFileURL(String bucketName, String targetName) throws CustomException {
        String fileUrl;
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                throw new CustomException(1000, "文件桶名称不存在");
            }
            FileAttributeDTO fileAttributeDTO = minioUtils.fileDetail(bucketName, targetName);
            Map<String, List<String>> hearder = fileAttributeDTO.getHearder();
            List<String> sourcefilenames = hearder.get("x-amz-meta-sourcefilename");
            HashMap<String, String> map = new HashMap<>();
            if (sourcefilenames != null && sourcefilenames.size() > 0) {
                String sourcefilename = sourcefilenames.get(0);
                String fileSuffix = StringUtils.substringAfter(fileAttributeDTO.getName(), ".");
                map.put("Content-Disposition", "attachment;filename=" + sourcefilename + "." + fileSuffix);
            }
            fileUrl = minioUtils.temporaryDownloadURL(bucketName, targetName, 60 * 5, map);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException(-1, e.getMessage());
        }
        return fileUrl;
    }

    /**
     * 获取文件流
     *
     * @param bucketName 文件桶名称
     * @param targetName 文件名
     * @return
     * @throws CustomException
     */
    public void getFile(String bucketName, String targetName, HttpServletResponse response) throws CustomException, IOException {
        InputStream stream = null;
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                throw new CustomException(1000, "文件桶名称不存在");
            }
            FileAttributeDTO fileAttributeDTO = minioUtils.fileDetail(bucketName, targetName);
            Map<String, List<String>> hearder = fileAttributeDTO.getHearder();
            List<String> sourcefilenames = hearder.get("x-amz-meta-sourcefilename");
            if (sourcefilenames != null && sourcefilenames.size() > 0) {
                String sourcefilename = sourcefilenames.get(0);
                String fileSuffix = StringUtils.substringAfter(fileAttributeDTO.getName(), ".");
                response.setHeader("Content-Disposition", "attachment;filename=" + sourcefilename + "." + fileSuffix);
            }
            stream = minioUtils.getFile(bucketName, targetName);
            ServletOutputStream outputStream = response.getOutputStream();
            ByteStreams.copy(stream, outputStream);
            stream.close();
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException(-1, e.getMessage());
        } finally {
            stream.close();
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName 文件桶名称
     * @param targetName 文件名称
     * @throws CustomException
     */
    public void deleteFile(String bucketName, String targetName) throws CustomException {
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                throw new CustomException(1000, "文件桶名称不存在");
            }
            minioUtils.deleteFile(bucketName, targetName);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException(-1, e.getMessage());
        }
    }

    /**
     * 文件详细内容
     *
     * @param bucketName 文件桶名称
     * @param targetName 文件名称
     * @return
     * @throws CustomException
     */
    public FileAttributeDTO fileDetail(String bucketName, String targetName) throws CustomException {
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                throw new CustomException(1000, "文件桶名称不存在");
            }
            FileAttributeDTO fileAttributeDTO = minioUtils.fileDetail(bucketName, targetName);
            return fileAttributeDTO;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException(-1, e.getMessage());
        }
    }

}
